package cn.harry.cabinet.arcface.util.camera;

import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * 相机辅助类，和{@link CameraListener}共同使用，获取nv21数据等操作
 */
public class CameraHelper implements Camera.PreviewCallback {
    private static final String TAG = "CameraHelper";
    private Camera mCamera;
    private int mCameraId;
    private Point previewViewSize;
    private View previewDisplayView;
    private Camera.Size previewSize;
    private Point specificPreviewSize;
    private int displayOrientation = 0;
    private int rotation;
    private int additionalRotation;
    private boolean isMirror = false;

    private Integer specificCameraId = null;
    private CameraListener cameraListener;

    private CameraHelper(Builder builder) {
        previewDisplayView = builder.previewDisplayView;
        specificCameraId = builder.specificCameraId;
        cameraListener = builder.cameraListener;
        rotation = builder.rotation;
        additionalRotation = builder.additionalRotation;
        previewViewSize = builder.previewViewSize;
        specificPreviewSize = builder.previewSize;
        if (builder.previewDisplayView instanceof TextureView) {
            isMirror = builder.isMirror;
        } else if (isMirror) {
            throw new RuntimeException("mirror is effective only when the preview is on a textureView");
        }
    }

    public void init() {
        if (previewDisplayView instanceof TextureView) {
            ((TextureView) this.previewDisplayView).setSurfaceTextureListener(textureListener);
        } else if (previewDisplayView instanceof SurfaceView) {
            ((SurfaceView) previewDisplayView).getHolder().addCallback(surfaceCallback);
        }

        if (isMirror) {
            previewDisplayView.setScaleX(-1);
        }
    }

    public void start() {
        synchronized (this) {
            if (mCamera != null) {
                return;
            }
            //相机数量为2则打开1,1则打开0,相机ID 1为前置，0为后置
            mCameraId = Camera.getNumberOfCameras() - 1;
            //若指定了相机ID且该相机存在，则打开指定的相机
            if (specificCameraId != null && specificCameraId <= mCameraId) {
                mCameraId = specificCameraId;
            }

            //没有相机
            if (mCameraId == -1) {
                if (cameraListener != null) {
                    cameraListener.onCameraError(new Exception("camera not found"));
                }
                return;
            }
            if (mCamera == null) {
                mCamera = Camera.open(mCameraId);
            }

            displayOrientation = getCameraOri(rotation);
            mCamera.setDisplayOrientation(displayOrientation);
            try {
                Camera.Parameters parameters = mCamera.getParameters();

                // 打印支持的预览格式
                List<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats();
                Log.i(TAG, "支持的预览格式: " + supportedPreviewFormats);
                for (Integer format : supportedPreviewFormats) {
                    Log.i(TAG, "格式代码: " + format + " (NV21=" + ImageFormat.NV21 + ", YV12=" + ImageFormat.YV12 + ", RGB_565=" + ImageFormat.RGB_565 + ")");
                }

                // 尝试设置最佳预览格式
                // 优先使用 NV21 格式（人脸识别引擎需要）
                // 注意：NV21 是 YUV 格式，包含彩色信息，但某些设备的 TextureView 可能显示为灰度
                if (supportedPreviewFormats.contains(ImageFormat.NV21)) {
                    parameters.setPreviewFormat(ImageFormat.NV21);
                    Log.i(TAG, "使用NV21格式");
                } else if (supportedPreviewFormats.contains(ImageFormat.YV12)) {
                    parameters.setPreviewFormat(ImageFormat.YV12);
                    Log.i(TAG, "使用YV12格式");
                } else if (supportedPreviewFormats.contains(ImageFormat.RGB_565)) {
                    parameters.setPreviewFormat(ImageFormat.RGB_565);
                    Log.i(TAG, "使用RGB_565格式");
                } else {
                    parameters.setPreviewFormat(ImageFormat.NV21); // 默认使用NV21
                    Log.i(TAG, "使用默认NV21格式");
                }

                //预览大小设置
                previewSize = parameters.getPreviewSize();
                List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();

                // 打印所有支持的预览尺寸
                Log.i(TAG, "支持的预览尺寸:");
                if (supportedPreviewSizes != null) {
                    for (Camera.Size size : supportedPreviewSizes) {
                        Log.i(TAG, "  " + size.width + "x" + size.height);
                    }
                }

                if (supportedPreviewSizes != null && !supportedPreviewSizes.isEmpty()) {
                    // 如果外部指定了预览尺寸，则优先按指定尺寸挑选（尽量接近或匹配）
                    if (specificPreviewSize != null) {
                        Camera.Size best = null;
                        int bestDiff = Integer.MAX_VALUE;
                        for (Camera.Size size : supportedPreviewSizes) {
                            int diff = Math.abs(size.width - specificPreviewSize.x) + Math.abs(size.height - specificPreviewSize.y);
                            if (diff < bestDiff) {
                                best = size;
                                bestDiff = diff;
                            }
                        }
                        if (best != null) {
                            previewSize = best;
                            Log.i(TAG, "按指定接近尺寸选择: " + previewSize.width + "x" + previewSize.height);
                        }
                    }

                    if (previewSize == null) {
                        previewSize = getBestSupportedSize(supportedPreviewSizes, previewViewSize);
                    }

                    // 上限限制，避免超大分辨率导致GraphicBuffer OOM
                    final int maxWidth = 1280;
                    final int maxHeight = 720;
                    if (previewSize.width > maxWidth || previewSize.height > maxHeight) {
                        Log.i(TAG, "预览尺寸过大: " + previewSize.width + "x" + previewSize.height + "，限制为不超过 " + maxWidth + "x" + maxHeight);
                        for (Camera.Size size : supportedPreviewSizes) {
                            if (size.width <= maxWidth && size.height <= maxHeight) {
                                previewSize = size;
                                Log.i(TAG, "降级到: " + previewSize.width + "x" + previewSize.height);
                                break;
                            }
                        }
                    }
                }
                parameters.setPreviewSize(previewSize.width, previewSize.height);
                Log.i(TAG, "最终使用预览尺寸: " + previewSize.width + "x" + previewSize.height);

                //对焦模式设置
                List<String> supportedFocusModes = parameters.getSupportedFocusModes();
                if (supportedFocusModes != null && !supportedFocusModes.isEmpty()) {
                    if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                    } else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    } else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                    }
                }

                // 尝试设置颜色效果为正常（确保不是黑白模式）
                List<String> supportedColorEffects = parameters.getSupportedColorEffects();
                if (supportedColorEffects != null && supportedColorEffects.contains(Camera.Parameters.EFFECT_NONE)) {
                    parameters.setColorEffect(Camera.Parameters.EFFECT_NONE);
                    Log.i(TAG, "设置颜色效果为正常模式");
                }

                // 检查并设置白平衡
                List<String> supportedWhiteBalance = parameters.getSupportedWhiteBalance();
                if (supportedWhiteBalance != null && supportedWhiteBalance.contains(Camera.Parameters.WHITE_BALANCE_AUTO)) {
                    parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
                    Log.i(TAG, "设置白平衡为自动模式");
                }

                // 打印当前摄像头参数用于调试
                Log.i(TAG, "当前预览格式: " + parameters.getPreviewFormat());
                Log.i(TAG, "当前颜色效果: " + parameters.getColorEffect());
                Log.i(TAG, "当前白平衡: " + parameters.getWhiteBalance());
                Log.i(TAG, "支持的颜色效果: " + supportedColorEffects);
                Log.i(TAG, "支持的白平衡模式: " + supportedWhiteBalance);
                mCamera.setParameters(parameters);
                mCamera.setPreviewCallback(this);
                
                if (previewDisplayView instanceof TextureView) {
                    SurfaceTexture surfaceTexture = ((TextureView) previewDisplayView).getSurfaceTexture();
                    if (surfaceTexture != null) {
                        mCamera.setPreviewTexture(surfaceTexture);
                        mCamera.startPreview();
                        Log.i(TAG, "设置预览纹理成功并启动预览");
                        
                        // 启动预览后检查颜色设置
                        checkAndFixColorSettings();
                    } else {
                        Log.w(TAG, "SurfaceTexture 为 null，等待 onSurfaceTextureAvailable 回调");
                        // 不在这里启动预览，等待 onSurfaceTextureAvailable 回调
                    }
                } else if (previewDisplayView instanceof SurfaceView) {
                    // SurfaceView 需要等待 surfaceCreated 回调
                    // 不在这里设置 PreviewDisplay 和启动预览
                    Log.i(TAG, "使用 SurfaceView，等待 surfaceCreated 回调");
                }

                if (cameraListener != null) {
                    cameraListener.onCameraOpened(mCamera, mCameraId, displayOrientation, isMirror);
                }
            } catch (Exception e) {
                if (cameraListener != null) {
                    cameraListener.onCameraError(e);
                }
            }
        }
    }

    private int getCameraOri(int rotation) {
        int degrees = rotation * 90;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
            default:
                break;
        }
        additionalRotation /= 90;
        additionalRotation *= 90;
        degrees += additionalRotation;
        int result;
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraId, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    public void stop() {
        synchronized (this) {
            if (mCamera == null) {
                return;
            }
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
            if (cameraListener != null) {
                cameraListener.onCameraClosed();
            }
        }
    }

    public boolean isStopped() {
        synchronized (this) {
            return mCamera == null;
        }
    }

    public void release() {
        synchronized (this) {
            stop();
            previewDisplayView = null;
            specificCameraId = null;
            cameraListener = null;
            previewViewSize = null;
            specificPreviewSize = null;
            previewSize = null;
        }
    }

    private Camera.Size getBestSupportedSize(List<Camera.Size> sizes, Point previewViewSize) {
        if (sizes == null || sizes.size() == 0) {
            return mCamera.getParameters().getPreviewSize();
        }
        Camera.Size[] tempSizes = sizes.toArray(new Camera.Size[0]);
        Arrays.sort(tempSizes, (o1, o2) -> {
            if (o1.width > o2.width) {
                return -1;
            } else if (o1.width == o2.width) {
                return o1.height > o2.height ? -1 : 1;
            } else {
                return 1;
            }
        });
        sizes = Arrays.asList(tempSizes);

        Camera.Size bestSize = sizes.get(0);
        float previewViewRatio;
        if (previewViewSize != null) {
            previewViewRatio = (float) previewViewSize.x / (float) previewViewSize.y;
        } else {
            previewViewRatio = (float) bestSize.width / (float) bestSize.height;
        }

        if (previewViewRatio > 1) {
            previewViewRatio = 1 / previewViewRatio;
        }
        boolean isNormalRotate = (additionalRotation % 180 == 0);

        for (Camera.Size s : sizes) {
            if (specificPreviewSize != null && specificPreviewSize.x == s.width && specificPreviewSize.y == s.height) {
                return s;
            }
            if (isNormalRotate) {
                if (Math.abs((s.height / (float) s.width) - previewViewRatio) < Math.abs(bestSize.height / (float) bestSize.width - previewViewRatio)) {
                    bestSize = s;
                }
            } else {
                if (Math.abs((s.width / (float) s.height) - previewViewRatio) < Math.abs(bestSize.width / (float) bestSize.height - previewViewRatio)) {
                    bestSize = s;
                }
            }
        }
        return bestSize;
    }

    public List<Camera.Size> getSupportedPreviewSizes() {
        if (mCamera == null) {
            return null;
        }
        return mCamera.getParameters().getSupportedPreviewSizes();
    }

    public List<Camera.Size> getSupportedPictureSizes() {
        if (mCamera == null) {
            return null;
        }
        return mCamera.getParameters().getSupportedPictureSizes();
    }

    /**
     * 检查并修复摄像头颜色设置
     */
    public void checkAndFixColorSettings() {
        if (mCamera == null) {
            return;
        }

        try {
            Camera.Parameters parameters = mCamera.getParameters();

            // 检查当前颜色效果
            String currentColorEffect = parameters.getColorEffect();
            Log.i(TAG, "当前颜色效果: " + currentColorEffect);

            // 如果是黑白效果，改为正常
            if (Camera.Parameters.EFFECT_MONO.equals(currentColorEffect) ||
                Camera.Parameters.EFFECT_BLACKBOARD.equals(currentColorEffect) ||
                Camera.Parameters.EFFECT_WHITEBOARD.equals(currentColorEffect)) {

                List<String> supportedColorEffects = parameters.getSupportedColorEffects();
                if (supportedColorEffects != null && supportedColorEffects.contains(Camera.Parameters.EFFECT_NONE)) {
                    parameters.setColorEffect(Camera.Parameters.EFFECT_NONE);
                    mCamera.setParameters(parameters);
                    Log.i(TAG, "已将颜色效果从 " + currentColorEffect + " 改为正常模式");
                }
            }

            // 检查白平衡设置
            String currentWhiteBalance = parameters.getWhiteBalance();
            Log.i(TAG, "当前白平衡: " + currentWhiteBalance);

        } catch (Exception e) {
            Log.e(TAG, "检查颜色设置时出错: " + e.getMessage());
        }
    }


    @Override
    public void onPreviewFrame(byte[] nv21, Camera camera) {
        if (cameraListener != null) {
            cameraListener.onPreview(nv21, camera);
        }
    }

    private TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
            Log.i(TAG, "onSurfaceTextureAvailable: " + width + "x" + height);
            if (mCamera != null) {
                try {
                    // 设置 SurfaceTexture 的默认缓冲区大小为预览尺寸
                    if (previewSize != null) {
                        surfaceTexture.setDefaultBufferSize(previewSize.width, previewSize.height);
                        Log.i(TAG, "设置 SurfaceTexture 缓冲区大小: " + previewSize.width + "x" + previewSize.height);
                    }
                    
                    mCamera.setPreviewTexture(surfaceTexture);
                    mCamera.startPreview();
                    Log.i(TAG, "在 SurfaceTexture 可用时启动预览");
                    
                    // 启动预览后检查颜色设置
                    checkAndFixColorSettings();
                } catch (IOException e) {
                    Log.e(TAG, "设置预览纹理失败", e);
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {
            Log.i(TAG, "onSurfaceTextureSizeChanged: " + width + "  " + height);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            // 停止相机并请求释放SurfaceTexture以回收相关显存
            stop();
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

        }
    };
    private SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Log.i(TAG, "surfaceCreated");
            if (mCamera != null) {
                try {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                    Log.i(TAG, "在 Surface 创建时启动预览");
                } catch (IOException e) {
                    Log.e(TAG, "设置预览显示失败", e);
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            stop();
        }
    };

    public void changeDisplayOrientation(int rotation) {
        if (mCamera != null) {
            this.rotation = rotation;
            displayOrientation = getCameraOri(rotation);
            mCamera.setDisplayOrientation(displayOrientation);
            if (cameraListener != null) {
                cameraListener.onCameraConfigurationChanged(mCameraId, displayOrientation);
            }
        }
    }
    public boolean switchCamera() {
        if (Camera.getNumberOfCameras() < 2) {
            return false;
        }
        // cameraId ,0为后置，1为前置
        specificCameraId = 1 - mCameraId;
        stop();
        start();
        return true;
    }

    public static final class Builder {

        /**
         * 预览显示的view，目前仅支持surfaceView和textureView
         */
        private View previewDisplayView;

        /**
         * 是否镜像显示，只支持textureView
         */
        private boolean isMirror;
        /**
         * 指定的相机ID
         */
        private Integer specificCameraId;
        /**
         * 事件回调
         */
        private CameraListener cameraListener;
        /**
         * 屏幕的长宽，在选择最佳相机比例时用到
         */
        private Point previewViewSize;
        /**
         * 传入getWindowManager().getDefaultDisplay().getRotation()的值即可
         */
        private int rotation;
        /**
         * 指定的预览宽高，若系统支持则会以这个预览宽高进行预览
         */
        private Point previewSize;

        /**
         * 额外的旋转角度（用于适配一些定制设备）
         */
        private int additionalRotation;

        public Builder() {
        }


        public Builder previewOn(View val) {
            if (val instanceof SurfaceView || val instanceof TextureView) {
                previewDisplayView = val;
                return this;
            } else {
                throw new RuntimeException("you must preview on a textureView or a surfaceView");
            }
        }


        public Builder isMirror(boolean val) {
            isMirror = val;
            return this;
        }

        public Builder previewSize(Point val) {
            previewSize = val;
            return this;
        }

        public Builder previewViewSize(Point val) {
            previewViewSize = val;
            return this;
        }

        public Builder rotation(int val) {
            rotation = val;
            return this;
        }

        public Builder additionalRotation(int val) {
            additionalRotation = val;
            return this;
        }

        public Builder specificCameraId(Integer val) {
            specificCameraId = val;
            return this;
        }

        public Builder cameraListener(CameraListener val) {
            cameraListener = val;
            return this;
        }

        public CameraHelper build() {
            if (previewViewSize == null) {
                Log.e(TAG, "previewViewSize is null, now use default previewSize");
            }
            if (cameraListener == null) {
                Log.e(TAG, "cameraListener is null, callback will not be called");
            }
            if (previewDisplayView == null) {
                throw new RuntimeException("you must preview on a textureView or a surfaceView");
            }
            return new CameraHelper(this);
        }
    }

}
